package ws

import (
	"context"
	"github.com/zeromicro/go-zero/core/fx"
	"github.com/zeromicro/go-zero/core/logx"
	"github.com/zeromicro/go-zero/core/stores/sqlx"
	"go-admin/base/dao"
	"go-admin/base/internal/svc"
	"go-admin/base/utils"
)

// ChatRoomServer 聊天室可以有很多个
type ChatRoomServer struct {
	svcCtx     *svc.ServiceContext
	ChatRooms  map[int64]*ChatRoom
	Clients    map[int64]*Client
	Register   chan *Client
	UnRegister chan *Client
	// 广播
	BroadcastData chan Message
}

var RoomServer *ChatRoomServer

func NewChatRoomServer(svcCtx *svc.ServiceContext) {
	// 加载所有的组
	groups, err := svcCtx.GroupModel.FindAll(context.Background())
	var crs []*ChatRoom
	if err != nil && err != sqlx.ErrNotFound {
		panic(err)
	}
	var groupIds []int64
	for _, group := range groups {
		groupIds = append(groupIds, group.Id)
	}
	if len(groupIds) > 0 {
		userGroups, err := svcCtx.UserGroupModel.FindByGroupIds(context.Background(), groupIds)
		if err != nil && err != sqlx.ErrNotFound {
			panic(err)
		}
		for _, group := range groups {
			userIds := utils.Collector[int64](fx.From(func(source chan<- any) {
				for _, userGroup := range userGroups {
					source <- userGroup
				}
			}).Filter(func(item any) bool {
				userGroup := item.(*dao.UserGroup)
				return group.Id == userGroup.GroupId.Int64
			}).Map(func(item any) any {
				userGroup := item.(*dao.UserGroup)
				return userGroup.UserId.Int64
			}))
			crs = append(crs, NewChatRoom(group.Id, group.Name.String, userIds))
		}
	}

	var crsMap map[int64]*ChatRoom = map[int64]*ChatRoom{}
	for _, cr := range crs {
		crsMap[cr.Id] = cr
	}
	RoomServer = &ChatRoomServer{
		svcCtx: svcCtx,
		// 暂时默认生成一个聊天室
		ChatRooms:     crsMap,
		Clients:       map[int64]*Client{},
		Register:      make(chan *Client, 100),
		UnRegister:    make(chan *Client, 100),
		BroadcastData: make(chan Message),
	}
}

func (crs *ChatRoomServer) Run() {
	for {
		select {
		case c := <-crs.Register:
			for i, _ := range crs.ChatRooms {
				if utils.IsContain(crs.ChatRooms[i].ClientIds, c.UserId) {
					crs.ChatRooms[i].Clients[c.UserId] = c
				}
			}
			crs.Clients[c.UserId] = c
			logx.Infof("%v,%v", c.UserId, "登录成功")
		case c := <-crs.UnRegister:
			for i, _ := range crs.ChatRooms {
				if utils.IsContain(crs.ChatRooms[i].ClientIds, c.UserId) {
					delete(crs.ChatRooms[i].Clients, c.UserId)
				}
			}
			delete(crs.Clients, c.UserId)
			c.Conn.Close()
			logx.Infof("%v,%v", c.UserId, "下线了。。。")
		case m := <-crs.BroadcastData:
			for _, v := range crs.ChatRooms[m.GroupMessage.GroupId].Clients {
				if m.GroupMessage.SenderId != v.UserId {
					v.Send <- m
				}
			}
		}
	}
}
